iT邦幫忙

第 12 屆 iThome 鐵人賽

DAY 14
0
自我挑戰組

純新手學習 JavaScript系列 第 14

新手學習JavaScript:day14 - 變數的有效範圍(2)

  • 分享至 

  • xImage
  •  

昨天我們聊了var的基本作用範圍,今天讓我們來介紹let/const的作用範圍,以及什麼是變數提升吧!

變數提升(hoisting)

什麼是hoisting?直接讓們來看下面的範例:

console.log(a); //undefined
var a = 3;

我們在先宣告a變數以前,就先嘗試用console.log(a)來印出a是什麼。結果不是印出3也不是印出ReferenceError: a is not defined,而是印出undefined。這種現象就叫做 Hoisting,變數的宣告被「提升」到最上面去了。所以上面的範例你可以想像成這樣子:

var a;
console.log(a) //undefined
a = 3;

也因為有這種特性,強烈建議所有可能用到的變數都盡量在 scope 的最上面先宣告完成後再使用。

補充: 用「提升」去形容這現象是為了方便理解,事實上程式碼位置是不會變動的。

let/const 與var 差異

let 跟 const 是在ES6之後才有的變數宣吿。前面我們在介紹變數宣告有提過他們跟var的宣告差異,let/const宣告之前就存取變數或常數會噴ReferenceError的錯誤,而var會印出undefine。

let與const 的作用域是以區塊也就是{}大括號做區隔,var是function。看下列簡單範例:

{
var a = 1;
let b = 2;
const c =3;
}

console.log(a); //1
console.log(b); //ReferenceError: b is not defined
console.log(c); //ReferenceError: c is not defined

那let 與 const 宣告會有hoisting的現象嗎?
我們把上面hoisting範例改一下:

function double(num){
console.log(x) //ReferenceError: Cannot access 'x' before initialization
let x = 2;
return num * 2;
}

double(5);

乍看之下let並沒有提升的問題,不會印出undefined 而是直接噴ReferenceError: Cannot access 'x' before initialization的錯誤訊息。let/const的這個特性稱作為(Temporal Dead Zone, TDZ)。

那為什麼會說乍看之下沒有提升問題呢?
如果把範例再改一下:

var x = 10;
function double(num){
console.log(x) //ReferenceError: Cannot access 'x' before initialization
let x = 2;
return num * 2;
}

double(5);

從上面的範例結果,可以看的出來其實,let是有hoisting的特性的。那到底hoisting背後的原理是什麼呢?有興趣的朋友可以去翻翻ES3規格書的第十章:Execution Contexts。

最後我們來補充一下,「全域物件」是什麼?
其實我們常常在說的「全域變數」指的就是「全域物件」的屬性。看下面範例:

var a =10; 

console.log(window.a); // 10

我們在最外層宣告變數a,一直以來我們都稱它「全域變數」,但從上面的結果可以發現,a其實是window物件下的ㄧ個屬性。所以,「全域變數」指的是「全域物件」的屬性。

以上就是今天的介紹!我們明天見!


上一篇
新手學習JavaScript:day13 - 變數的有效範圍(Scope)
下一篇
新手學習JavaScript:day15 - 變數的更新與傳遞
系列文
純新手學習 JavaScript30
圖片
  直播研討會
圖片
{{ item.channelVendor }} {{ item.webinarstarted }} |
{{ formatDate(item.duration) }}
直播中

尚未有邦友留言

立即登入留言